# Разработанная программа должна удовлетворять следующим требованиям:

* Класс, коллекцией экземпляров которого управляет программа, должен реализовывать сортировку по умолчанию.
* Все требования к полям класса (указанные в виде комментариев) должны быть выполнены.
* Для хранения необходимо использовать коллекцию типа **java.util.PriorityQueue**
* При запуске приложения коллекция должна автоматически заполняться значениями из файла.
* Имя файла должно передаваться программе с помощью: переменная окружения.
* Данные должны храниться в файле в формате **json**
* Чтение данных из файла необходимо реализовать с помощью класса **java.util.Scanner**
* Запись данных в файл необходимо реализовать с помощью класса **java.io.FileOutputStream**
* Все классы в программе должны быть задокументированы в формате **javadoc**.
* Программа должна корректно работать с неправильными данными (ошибки пользовательского ввода, отсутсвие прав доступа к файлу и т.п.)

## В интерактивном режиме программа должна поддерживать выполнение следующих команд:

* **help** : вывести справку по доступным командам
* **info** : вывести в стандартный поток вывода информацию о коллекции (тип, дата инициализации, количество элементов и т.д.)
* **show** : вывести в стандартный поток вывода все элементы коллекции в строковом представлении
* **add {element}** : добавить новый элемент в коллекцию
* **update id {element}** : обновить значение элемента коллекции, id которого равен заданному
* **remove_by_id id** : удалить элемент из коллекции по его id
* **clear** : очистить коллекцию
* **save** : сохранить коллекцию в файл
* **execute_script file_name** : считать и исполнить скрипт из указанного файла. В скрипте содержатся команды в таком же виде, в котором их вводит пользователь в интерактивном режиме.
* **exit** : завершить программу (без сохранения в файл)
* **add_if_min {element}** : добавить новый элемент в коллекцию, если его значение меньше, чем у наименьшего элемента этой коллекции
* **remove_greater {element}** : удалить из коллекции все элементы, превышающие заданный
* **remove_lower {element}** : удалить из коллекции все элементы, меньшие, чем заданный
* **remove_all_by_oscars_count oscarsCount** : удалить из коллекции все элементы, значение поля oscarsCount которого эквивалентно заданному
* **remove_any_by_director director** : удалить из коллекции один элемент, значение поля director которого эквивалентно заданному
* **print_field_descending_oscars_count** : вывести значения поля oscarsCount всех элементов в порядке убывания
------
## Описание хранимых в коллекции классов:
```
public class Movie {
    private int id; //Значение поля должно быть больше 0, Значение этого поля должно быть уникальным, Значение этого поля должно генерироваться автоматически
    private String name; //Поле не может быть null, Строка не может быть пустой
    private Coordinates coordinates; //Поле не может быть null
    private java.time.LocalDateTime creationDate; //Поле не может быть null, Значение этого поля должно генерироваться автоматически
    private int oscarsCount; //Значение поля должно быть больше 0
    private MovieGenre genre; //Поле может быть null
    private MpaaRating mpaaRating; //Поле может быть null
    private Person director; //Поле может быть null
}
public class Coordinates {
    private long x; //Значение поля должно быть больше -312
    private Double y; //Значение поля должно быть больше -901, Поле не может быть null
}
public class Person {
    private String name; //Поле не может быть null, Строка не может быть пустой
    private float height; //Значение поля должно быть больше 0
    private Color eyeColor; //Поле может быть null
    private Color hairColor; //Поле не может быть null
    private Country nationality; //Поле не может быть null
    private Location location; //Поле может быть null
}
public class Location {
    private long x;
    private float y;
    private long z;
    private String name; //Длина строки не должна быть больше 233, Поле может быть null
}
public enum MovieGenre {
    ACTION,
    DRAMA,
    ADVENTURE;
}
public enum MpaaRating {
    PG,
    PG_13,
    R,
    NC_17;
}
public enum Color {
    BLUE,
    ORANGE,
    WHITE,
    BROWN;
}
public enum Color {
    GREEN,
    BLACK,
    YELLOW;
}
public enum Country {
    GERMANY,
    NORTH_KOREA,
    JAPAN;
}
```

***

### Разделить программу на клиентский и серверный модули. Серверный модуль должен осуществлять выполнение команд по управлению коллекцией. Клиентский модуль должен в интерактивном режиме считывать команды, передавать их для выполнения на сервер и выводить результаты выполнения.

* Операции обработки объектов коллекции должны быть реализованы с помощью **Stream API** с использованием лямбда-выражений.
* Объекты между клиентом и сервером должны передаваться в сериализованном виде.
* Объекты в коллекции, передаваемой клиенту, должны быть отсортированы по названию
* Клиент должен корректно обрабатывать временную недоступность сервера.
* Обмен данными между клиентом и сервером должен осуществляться по протоколу **TCP**
* Для обмена данными на сервере необходимо использовать **потоки ввода-вывода**
* Для обмена данными на клиенте необходимо использовать **сетевой канал**
* Сетевые каналы должны использоваться в **неблокирующем режиме**
* Организовать хранение коллекции в реляционной СУБД (**PostgresQL**). Убрать хранение коллекции в файле.
* Для генерации поля id использовать средства базы данных (**sequence**).
* Обновлять состояние коллекции в памяти только при успешном добавлении объекта в БД
* Все команды получения данных должны работать с коллекцией в памяти, а не в БД
* Организовать возможность регистрации и авторизации пользователей. У пользователя есть возможность указать пароль.
* Пароли при хранении хэшировать алгоритмом **MD5**
* Запретить выполнение команд не авторизованным пользователям.
* При хранении объектов сохранять информацию о пользователе, который создал этот объект.
* Пользователи должны иметь возможность просмотра всех объектов коллекции, но модифицировать могут только принадлежащие им.
* Для идентификации пользователя отправлять логин и пароль с каждым запросом.

### Необходимо реализовать многопоточную обработку запросов.

* Для многопоточного чтения запросов использовать создание нового потока (**java.lang.Thread**)
* Для многопотчной обработки полученного запроса использовать **ForkJoinPool**
* Для многопоточной отправки ответа использовать **ForkJoinPool**
* Для синхронизации доступа к коллекции использовать **java.util.Collections.synchronizedXXX**

+ Интерфейс должен быть реализован с помощью библиотеки JavaFX
+ Графический интерфейс клиентской части должен поддерживать русский, финский, украинский и английский (Южная Африка) языки / локали. Должно обеспечиваться корректное отображение чисел, даты и времени в соответстии с локалью. Переключение языков должно происходить без перезапуска приложения. Локализованные ресурсы должны храниться в классе.

---

### В функционал клиента должно входить:

* Окно с авторизацией/регистрацией.
* Отображение текущего пользователя.
* Таблица, отображающая все объекты из коллекции
* Каждое поле объекта - отдельная колонка таблицы.
* Строки таблицы можно фильтровать/сортировать по значениям любой из колонок. Сортировку и фильтрацию значений столбцов реализовать с помощью Streams API.
* Поддержка всех команд из предыдущих лабораторных работ.
* Область, визуализирующую объекты коллекции
* Объекты должны быть нарисованы с помощью графических примитивов с использованием Graphics, Canvas или аналогичных средств графической библиотеки.
* При визуализации использовать данные о координатах и размерах объекта.
* Объекты от разных пользователей должны быть нарисованы разными цветами.
* При нажатии на объект должна выводиться информация об этом объекте.
* При добавлении/удалении/изменении объекта, он должен автоматически появиться/исчезнуть/измениться  на области как владельца, так и всех других клиентов.
* При отрисовке объекта должна воспроизводиться согласованная с преподавателем анимация.
* Возможность редактирования отдельных полей любого из объектов (принадлежащего пользователю). Переход к редактированию объекта возможен из таблицы с общим списком объектов и из области с визуализацией объекта.
* Возможность удаления выбранного объекта (даже если команды remove ранее не было).

---
# Запуск

1. В файле *config.properties* укажите данные для подключения к базе данных.
2. В базе данных создайте необходимые таблицы:
```
CREATE TABLE my_users (    id SERIAL PRIMARY KEY,    username VARCHAR(255) NOT NULL,    password VARCHAR(255) NOT NULL);
CREATE TABLE movie_table (    id SERIAL PRIMARY KEY,    name VARCHAR(255) NOT NULL,    creation_date BIGINT NOT NULL,    oscars_count BIGINT,    genre VARCHAR(255) NOT NULL,    mpaa_rating VARCHAR(255) NOT NULL,    coordinates_x DOUBLE PRECISION NOT NULL,    coordinates_y INT NOT NULL,    director_name VARCHAR(255) NOT NULL,    director_height DOUBLE PRECISION NOT NULL,    director_eye_color VARCHAR(255) NOT NULL,    director_hair_color VARCHAR(255) NOT NULL,    director_nationality VARCHAR(255) NOT NULL,    director_location_x DOUBLE PRECISION NOT NULL,    director_location_y DOUBLE PRECISION NOT NULL,    director_location_z DOUBLE PRECISION NOT NULL,    director_location_name VARCHAR(255) NOT NULL,    user_id BIGINT NOT NULL,    FOREIGN KEY (user_id) REFERENCES my_users(id));
```
3. Соберите сервер:
```
mvn clean package
```
4. Запустите сервер:
```
java -jar target/application-1.0-jar-with-dependencies.jar
```
5. Для запуска клиента откройте проект в IDE и запустите com.example.vt_labs_1.App (дада я не осилил подтянуть JavaFX в джарник, ну может потом как-нибудь руки дойдут).
---